﻿using System.Reactive;
using System.Threading.Tasks;
using IniFileParser.Model;
using MilkTeaMachine.OfflineClient.Utils;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;

namespace MilkTeaMachine.OfflineClient.ViewModels;

public class FactorySettingsViewModel : ViewModelBase, IRoutableViewModel
{
    private readonly IniFileParser.IniFileParser _parser;

    public FactorySettingsViewModel(IScreen hostScreen)
    {
        HostScreen = hostScreen;
        _parser = new IniFileParser.IniFileParser();
        var data = _parser.ReadFile("Configuration/config.ini");
        MotorSpeed = data["Machine"]["speed"];
        Acceleration = data["Machine"]["acceleration"];
        Direction = data["Machine"]["direction"];
        var addressSection = data["Address"];
        DisplayAddress(addressSection);
        SaveAndQuitCmd = ReactiveCommand.CreateFromTask(SaveAndQuitAsync);
    }

    public FactorySettingsViewModel(): this(default!)
    {
        
    }

    private Task SaveAndQuitAsync()
    {
        var success = ValidateData();
        if (!success)
            return Task.CompletedTask;
        var data = _parser.ReadFile("Configuration/config.ini");
        data["Machine"]["speed"] = MotorSpeed;
        data["Machine"]["acceleration"] = Acceleration;
        data["Machine"]["direction"] = Direction;
        SetAddress(data["Address"]);
        _parser.WriteFile("Configuration/config.ini", data);
        HostScreen.Router.NavigateBack.Execute();
        return Task.CompletedTask;
    }

    private void SetAddress(KeyDataCollection section)
    {
        section["Address11"] = Inner11;
        section["Address12"] = Inner12;
        section["Address13"] = Inner13;
        section["Address14"] = Inner14;
        section["Address15"] = Inner15;
        section["Address16"] = Inner16;
        section["Address21"] = Outer21;
        section["Address22"] = Outer22;
        section["Address23"] = Outer23;
        section["Address24"] = Outer24;
        section["Address31"] = Outer31;
        section["Address32"] = Outer32;
        section["Address33"] = Outer33;
        section["Address34"] = Outer34;
        section["Address41"] = Outer41;
        section["Address42"] = Outer42;
        section["Address43"] = Outer43;
        section["Address44"] = Outer44;
        section["Address51"] = Outer51;
        section["Address52"] = Outer52;
        section["Address53"] = Outer53;
        section["Address54"] = Outer54;
    }

    private bool ValidateData()
    {
        if (
            int.TryParse(Inner11, out _) &&
            int.TryParse(Inner12, out _) &&
            int.TryParse(Inner13, out _) &&
            int.TryParse(Inner14, out _) &&
            int.TryParse(Inner15, out _) &&
            int.TryParse(Inner16, out _) &&
            int.TryParse(Outer21, out _) &&
            int.TryParse(Outer22, out _) &&
            int.TryParse(Outer23, out _) &&
            int.TryParse(Outer24, out _) &&
            int.TryParse(Outer31, out _) &&
            int.TryParse(Outer32, out _) &&
            int.TryParse(Outer33, out _) &&
            int.TryParse(Outer34, out _) &&
            int.TryParse(Outer41, out _) &&
            int.TryParse(Outer42, out _) &&
            int.TryParse(Outer43, out _) &&
            int.TryParse(Outer44, out _) &&
            int.TryParse(Outer51, out _) &&
            int.TryParse(Outer52, out _) &&
            int.TryParse(Outer53, out _) &&
            int.TryParse(Outer54, out _))
        {
            if (!int.TryParse(MotorSpeed, out _) && !int.TryParse(Acceleration, out _))
            {
                MessageBoxUtil.GetBox("输入速度和加速度格式错误");
                return false;
            }

            if (Direction?.Trim() != "0" && Direction?.Trim() != "1")
            {
                MessageBoxUtil.GetBox("方向只能为0(顺时针)或1(逆时针)");
                return false;
            }

            return true;
        }

        MessageBoxUtil.GetBox("输入地址格式错误");
        return false;
    }

    private void DisplayAddress(KeyDataCollection section)
    {
        Inner11 = section["Address11"];
        Inner12 = section["Address12"];
        Inner13 = section["Address13"];
        Inner14 = section["Address14"];
        Inner15 = section["Address15"];
        Inner16 = section["Address16"];
        Outer21 = section["Address21"];
        Outer22 = section["Address22"];
        Outer23 = section["Address23"];
        Outer24 = section["Address24"];
        Outer31 = section["Address31"];
        Outer32 = section["Address32"];
        Outer33 = section["Address33"];
        Outer34 = section["Address34"];
        Outer41 = section["Address41"];
        Outer42 = section["Address42"];
        Outer43 = section["Address43"];
        Outer44 = section["Address44"];
        Outer51 = section["Address51"];
        Outer52 = section["Address52"];
        Outer53 = section["Address53"];
        Outer54 = section["Address54"];
    }

    public string? UrlPathSegment { get; } = nameof(FactorySettingsViewModel);
    public IScreen HostScreen { get; }
    [Reactive] public string MotorSpeed { get; set; }
    [Reactive] public string Acceleration { get; set; }
    [Reactive] public string? Direction { get; set; }
    [Reactive] public string? Inner11 { get; set; }
    [Reactive] public string? Inner12 { get; set; }
    [Reactive] public string? Inner13 { get; set; }
    [Reactive] public string? Inner14 { get; set; }
    [Reactive] public string? Inner15 { get; set; }
    [Reactive] public string? Inner16 { get; set; }
    [Reactive] public string? Outer21 { get; set; }
    [Reactive] public string? Outer22 { get; set; }
    [Reactive] public string? Outer23 { get; set; }
    [Reactive] public string? Outer24 { get; set; }
    [Reactive] public string? Outer31 { get; set; }
    [Reactive] public string? Outer32 { get; set; }
    [Reactive] public string? Outer33 { get; set; }
    [Reactive] public string? Outer34 { get; set; }
    [Reactive] public string? Outer41 { get; set; }
    [Reactive] public string? Outer42 { get; set; }
    [Reactive] public string? Outer43 { get; set; }
    [Reactive] public string? Outer44 { get; set; }
    [Reactive] public string? Outer51 { get; set; }
    [Reactive] public string? Outer52 { get; set; }
    [Reactive] public string? Outer53 { get; set; }
    [Reactive] public string? Outer54 { get; set; }
    public ReactiveCommand<Unit, Unit> SaveAndQuitCmd { get; }
}